package com.time.auth.domain.service.impl;

import cn.dev33.satoken.secure.SaSecureUtil;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.google.gson.Gson;
import com.time.auth.common.enums.AuthRoleTypeEnum;
import com.time.auth.common.enums.AuthUserStatusEnum;
import com.time.auth.common.enums.AuthUserTypeEnum;
import com.time.auth.common.enums.IsDeletedFlagEnum;
import com.time.auth.common.utils.CollectionUtils;
import com.time.auth.domain.constants.AuthConstant;
import com.time.auth.domain.constants.ExceptionCode;
import com.time.auth.domain.convent.AuthAdminUserBOConverter;
import com.time.auth.domain.entity.AuthAdminUserBO;
import com.time.auth.domain.exception.NotFoundDomainException;
import com.time.auth.domain.exception.UserAlreadyExistsException;
import com.time.auth.domain.exception.UserLoginException;
import com.time.auth.domain.exception.UserRegisterException;
import com.time.auth.domain.redis.RedisUtil;
import com.time.auth.domain.service.AuthAdminUserDomainService;
import com.time.auth.infra.basic.entity.*;
import com.time.auth.infra.basic.service.*;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 管理员用户领域层实现类
 *
 * @author: HuangQi
 * @date: Created in 16:06 2025/9/29
 * @description: 管理员用户领域层实现类
 */
@Slf4j
@Service("authAdminUserDomainService")
public class AuthAdminUserDomainServiceImpl implements AuthAdminUserDomainService {

    private static final String salt = "timecollector";

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private AuthAdminUserService authAdminUserService;

    @Autowired
    private AuthRoleService authRoleService;

    @Autowired
    private AuthUserRoleService authUserRoleService;

    @Autowired
    private AuthPermissionService authPermissionService;

    @Autowired
    private AuthRolePermissionService authRolePermissionService;

    @Override
    @SneakyThrows
    @Transactional(rollbackFor = Exception.class)
    public Boolean register(AuthAdminUserBO authAdminUserBO, Integer userType) {
        if (log.isInfoEnabled()) {
            log.info("AuthAdminUserDomainServiceImpl.register.bo:{}", authAdminUserBO);
        }

        // 参数转换
        AuthAdminUser authAdminUser = AuthAdminUserBOConverter.INSTANCE.convertBOToEntity(authAdminUserBO);
        // 检查管理员用户是否已经存在
        if (isExistAdminUser(authAdminUser.getUserName())) {
            throw new UserAlreadyExistsException(ExceptionCode.ADMIN_USER_ALREADY_EXISTS, "该管理员用户已经存在");
        }

        // 密码加密
        if (StringUtils.isBlank(authAdminUser.getPassword())) {
            authAdminUser.setPassword(AuthConstant.DEFAULT_ADMIN_USER_PASSWORD);
        }

        authAdminUser.setPassword(SaSecureUtil.md5BySalt(authAdminUser.getPassword(), salt));

        // 设置默认头像
        if (StringUtils.isBlank(authAdminUser.getAvatarUrl())) {
            authAdminUser.setAvatarUrl(AuthConstant.DEFAULT_ADMIN_USER_AVATAR);
        }

        authAdminUser.setStatus(AuthUserStatusEnum.OPEN.getCode());
        authAdminUser.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());

        // 调用service
        Integer count = authAdminUserService.insert(authAdminUser);

        if (count <= 0) {
            throw new UserRegisterException(ExceptionCode.ADMIN_USER_REGISTER_ERROR, "用户注册失败");
        }

        // 建立初步的用户角色关联（普通用户-游客）
        AuthRole authRole = new AuthRole();
        authRole.setRoleKey(AuthRoleTypeEnum.fromCode(userType));
        authRole.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
        AuthRole roleResult = authRoleService.queryByCondtion(authRole);
        if (Objects.isNull(roleResult)) {
            throw new UserRegisterException(ExceptionCode.ADMIN_USER_REGISTER_WITHOUR_ROLE, "管理员用户注册失败，未找到默认角色");
        }
        Long roleId = roleResult.getId();
        Long adminUserId = authAdminUser.getAdminId();

        // 建立用户和角色的关联(插入一条数据到用户角色关联表)
        AuthUserRole authUserRole = new AuthUserRole();
        authUserRole.setUserId(adminUserId);
        authUserRole.setRoleId(roleId);
        authUserRole.setUserType(AuthUserTypeEnum.ADMIN.getDesc());
        authUserRole.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
        Integer userRoleCount = authUserRoleService.insert(authUserRole);
        if (userRoleCount <= 0) {
            throw new UserRegisterException(ExceptionCode.ADMIN_USER_REGISTER_WITHOUR_ROLE, "管理员用户注册失败，用户角色关联失败");
        }

        // 在角色权限表中查询permissionId集合
        AuthRolePermission authRolePermission = new AuthRolePermission();
        authRolePermission.setRoleId(roleId);
        authRolePermission.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());

        List<AuthRolePermission> authRolePermissionList = authRolePermissionService.queryByCondition(authRolePermission);
        if (CollectionUtils.isEmpty(authRolePermissionList)) {
            throw new UserRegisterException(ExceptionCode.ADMIN_USER_REGISTER_WITHOUR_PERMISSION, "管理员用户注册失败，未找到默认权限");
        }
        List<Long> permissionIdList = authRolePermissionList.stream()
                .map(AuthRolePermission::getPermissionId).collect(Collectors.toList());

        // 根据 permission id 去权限表中查权限
        List<AuthPermission> permissionList = authPermissionService.queryByPermisionIdList(permissionIdList);
        String permissionKey = redisUtil.buildKey(AuthConstant.AUTH_PERMISSION_ADMIN_PREFIX, authAdminUser.getUserName());
        redisUtil.set(permissionKey, new Gson().toJson(permissionList));
        return true;
    }

    /**
     * 检查管理员用户是否已经存在
     *
     * @param userName 用管理员户名
     * @return 管理员用户是否存在, true: 存在, false: 不存在
     */
    private Boolean isExistAdminUser(String userName) {
        AuthAdminUser authUser = authAdminUserService.queryByUserName(userName);
        return !Objects.isNull(authUser);
    }

    @Override
    public Boolean update(AuthAdminUserBO authAdminUserBO) {
        if (log.isInfoEnabled()) {
            log.info("AuthAdminUserDomainServiceImpl.update.bo:{}", authAdminUserBO);
        }

        // 参数转换
        AuthAdminUser authAdminUser = AuthAdminUserBOConverter.INSTANCE.convertBOToEntity(authAdminUserBO);

        // 检查该用户是否存在
        if (isExistAdminUser(authAdminUser.getUserName())) {
            throw new NotFoundDomainException(ExceptionCode.ADMIN_USER_NOT_FOUND, "该管理员用户不存在");
        }

        // 调用service
        Integer count = authAdminUserService.updateByUserName(authAdminUser);

        // 返回结果
        return count > 0;
    }

    @Override
    public AuthAdminUserBO getUserInfo(AuthAdminUserBO authAdminUserBO) {
        if (log.isInfoEnabled()) {
            log.info("AuthAdminUserDomainServiceImpl.getUserInfo.bo:{}", authAdminUserBO);
        }

        // 参数转换
        AuthAdminUser authAdminUser = AuthAdminUserBOConverter.INSTANCE.convertBOToEntity(authAdminUserBO);
        authAdminUser.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());

        // 调用 service
        List<AuthAdminUser> userList = authAdminUserService.queryByCondition(authAdminUser);
        if (CollectionUtils.isEmpty(userList)) {
            return new AuthAdminUserBO();
        }

        AuthAdminUser userInfo = userList.get(0);
        return AuthAdminUserBOConverter.INSTANCE.convertEntityToBO(userInfo);
    }

    @Override
    public SaTokenInfo doLogin(String userName, String password) {
        if (log.isInfoEnabled()) {
            log.info("AuthAdminUserDomainServiceImpl.doLogin.userName:{}, password:{}", userName, password);
        }

        // 根据用户名判断用户是否存在
        // 判断用户是否存在，不存在则注册
        AuthAdminUser authAdminUser = authAdminUserService.queryByUserName(userName);
        if (Objects.isNull(authAdminUser)) {
            throw new UserLoginException(ExceptionCode.ADMIN_USER_LOGIN_ERROR, "管理员用户登录失败，没有这个用户");
        }

        // 用户存在验证密码是否正确
        String input_password = SaSecureUtil.md5BySalt(password, salt);
        if (!authAdminUser.getPassword().equals(input_password)) {
            throw new UserLoginException(ExceptionCode.ADMIN_USER_LOGIN_ERROR, "管理员用户登录失败，密码错误");
        }

        // 登录
        String openId = AuthUserTypeEnum.ADMIN.getDesc() + userName;
        StpUtil.login(openId);
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
        log.info("管理员登录成功,tokenInfo:{}", JSON.toJSONString(tokenInfo));

        // 返回结果
        return tokenInfo;
    }

    @Override
    public Boolean delete(AuthAdminUserBO authAdminUserBO) {
        if (log.isInfoEnabled()) {
            log.info("AuthAdminUserDomainServiceImpl.delete.bo:{}", JSON.toJSONString(authAdminUserBO));
        }

        // 参数转换
        AuthAdminUser authAdminUser = AuthAdminUserBOConverter.INSTANCE.convertBOToEntity(authAdminUserBO);
        authAdminUser.setIsDeleted(IsDeletedFlagEnum.DELETED.getCode());

        // 调用service
        Integer count = authAdminUserService.update(authAdminUser);

        // 删除该用户保留的 redis 缓存
        if (count > 0) {
            String permissionKey = redisUtil.buildKey(AuthConstant.AUTH_ROLE_ADMIN_PREFIX, authAdminUser.getUserName());
            redisUtil.del(permissionKey);
        }

        // 删除用户角色关联信息
        if (count > 0) {
            AuthUserRole authUserRole = new AuthUserRole();
            authUserRole.setUserId(authAdminUser.getAdminId());
            authUserRole.setUserType(AuthUserTypeEnum.ADMIN.getDesc());
            authUserRole.setIsDeleted(IsDeletedFlagEnum.DELETED.getCode());
            Integer update_count = authUserRoleService.updateByUserId(authUserRole);
        }

        // 返回结果
        return count > 0;
    }


}
